package com.zkb.modules.sys.controller;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Set;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zkb.common.constant.CoreConst;
import com.zkb.common.util.AuthorizationUtils;
import com.zkb.common.util.PageUtil;
import com.zkb.common.util.StringUtils;
import com.zkb.common.util.UUIDUtil;
import com.zkb.common.util.text.Convert;
import com.zkb.common.vo.AjaxResultVo;
import com.zkb.modules.base.BaseController;
import com.zkb.modules.sys.model.SysMenu;
import com.zkb.modules.sys.model.SysRole;
import com.zkb.modules.sys.model.SysUser;
import com.zkb.modules.sys.service.MenuService;
import com.zkb.modules.sys.service.RoleService;
import com.zkb.modules.sys.service.UserService;
import com.zkb.modules.sys.vo.MenuTreeListVo;

@Controller
@RequestMapping("/role")
public class RoleController extends BaseController {

	@Autowired
	private RoleService roleService;

	@Autowired
	private MenuService menuService;

	@Autowired
	private UserService userService;

	/**
	 * 权限管理--角色管理
	 */
	@GetMapping("/toRolePage")
	public String roleList() {
		return "role/list";
	}

	/**
	 * 角色列表数据
	 * 
	 * @param role
	 * @param limit
	 * @param offset
	 * @return
	 */
	@RequiresPermissions("role:list")
	@PostMapping("/list")
	@ResponseBody
	public AjaxResultVo pageRoles(SysRole role, Integer limit, Integer offset) {
		try {
			PageHelper.startPage(PageUtil.getPageNo(limit, offset), limit);
			List<SysRole> roleList = roleService.listRoles(role);
			PageInfo<SysRole> pageResult = new PageInfo<>(roleList);
			AjaxResultVo resultVo = AjaxResultVo.success();
			resultVo.put("rows", pageResult.getList());
			resultVo.put("total", pageResult.getTotal());
			return resultVo;
		} catch (Exception e) {
			logger.error(String.format("角色列表查询异常 RoleController.pageRoles%s", e));
			return AjaxResultVo.error("查询失败");
		}
	}

	/**
	 * 跳转新增角色
	 * 
	 * @return
	 */
	@RequiresPermissions("role:add")
	@GetMapping("/add")
	public String add() {
		return "role/add";
	}

	/**
	 * 新增角色
	 * 
	 * @param role
	 * @return
	 */
	@RequiresPermissions("role:add")
	@PostMapping("/doAdd")
	@ResponseBody
	public AjaxResultVo addRole(SysRole role) {
		try {
			Date nowDate = new Date();
			role.setRoleId(Long.valueOf(UUIDUtil.getUniqueIdByUUId()));
			role.setCreateTime(nowDate);
			role.setUpdateTime(nowDate);
			if (roleService.save(role)) {
				return AjaxResultVo.success("添加角色成功");
			} else {
				return AjaxResultVo.error("添加角色失败");
			}
		} catch (Exception e) {
			logger.error(String.format("角色添加异常 RoleController.addRole%s", e));
			return AjaxResultVo.error("添加角色失败");
		}
	}

	/**
	 * 编辑角色详情
	 * 
	 * @param model
	 * @param roleId
	 * @return
	 */
	@RequiresPermissions("role:edit")
	@GetMapping("/edit")
	public String detail(Model model, String roleId) {
		SysRole role = roleService.getSysRoleById(Long.valueOf(roleId));
		model.addAttribute("role", role);
		return "role/detail";
	}

	/**
	 * 编辑角色
	 * 
	 * @param role
	 * @return
	 */
	@RequiresPermissions("role:edit")
	@PostMapping("/edit")
	@ResponseBody
	public AjaxResultVo editRole(SysRole role) {
		try {
			role.setUpdateTime(new Date());
			if (roleService.updateById(role)) {
				return AjaxResultVo.success("编辑角色成功");
			} else {
				return AjaxResultVo.error("编辑角色失败");
			}
		} catch (Exception e) {
			logger.error(String.format("角色编辑异常 RoleController.editRole%s", e));
			return AjaxResultVo.error("编辑角色失败");
		}
	}

	/**
	 * 删除角色
	 * 
	 * @param roleId
	 * @return
	 */
	@RequiresPermissions("role:delete")
	@PostMapping("/delete")
	@ResponseBody
	public AjaxResultVo deleteRole(String roleId) {
		try {
			if (StringUtils.isEmpty(roleId)) {
				return AjaxResultVo.error("删除失败,未选择删除选项");
			}
			Long[] roleIds = { Long.valueOf(roleId) };
			if (roleService.listAllUsersByRoleIds(roleIds).size() > 0) {
				return AjaxResultVo.error("删除失败,该角色下存在用户");
			}
			List<Long> roleIdsList = Arrays.asList(roleIds);
			if (roleService.removeByIds(roleIdsList)) {
				// 删除角色菜单关系
				if (roleService.batchRemoveRoleAndMenu(roleIdsList)) {
					return AjaxResultVo.success("删除角色成功");
				} else {
					return AjaxResultVo.error("删除角色失败");
				}
			} else {
				return AjaxResultVo.error("删除角色失败");
			}
		} catch (Exception e) {
			logger.error(String.format("角色删除异常 RoleController.deleteRole%s", e));
			return AjaxResultVo.error("删除角色失败");
		}
	}

	/**
	 * 批量删除角色
	 * 
	 * @param roleIdStr
	 * @return
	 */
	@RequiresPermissions("role:delete")
	@PostMapping("/batch/delete")
	@ResponseBody
	public AjaxResultVo batchDeleteRole(String roleIdStr) {
		try {
			Long[] roleIdsArray = Convert.toLongArray(",", roleIdStr);
			if (StringUtils.isEmpty(roleIdsArray)) {
				return AjaxResultVo.error("删除失败,未选择删除选项");
			}
			if (roleService.listAllUsersByRoleIds(roleIdsArray).size() > 0) {
				return AjaxResultVo.error("删除失败,选择的角色下存在用户");
			}
			List<Long> roleIdsList = Arrays.asList(roleIdsArray);
			if (roleService.removeByIds(roleIdsList)) {
				// 删除角色菜单关系
				if (roleService.batchRemoveRoleAndMenu(roleIdsList)) {
					return AjaxResultVo.success("删除角色成功");
				} else {
					return AjaxResultVo.error("删除角色失败");
				}
			} else {
				return AjaxResultVo.error("删除角色失败");
			}
		} catch (Exception e) {
			logger.error(String.format("批量删除角色异常 RoleController.batchDeleteRole%s", e));
			return AjaxResultVo.error("删除角色失败");
		}
	}

	/**
	 * 分配权限详情
	 * 
	 * @param model
	 * @param roleId
	 * @return
	 */
	@RequiresPermissions("role:edit")
	@GetMapping("/assignMenus")
	public String assignMenus(Model model, String roleId) {
		model.addAttribute("roleId", roleId);
		return "role/assignmenus";
	}

	/**
	 * 分配权限列表查询
	 * 
	 * @param roleId
	 * @return
	 */
	@RequiresPermissions("role:edit")
	@PostMapping("/assign/menu/list")
	@ResponseBody
	public List<MenuTreeListVo> assignRole(String roleId) {
		List<MenuTreeListVo> listVos = new ArrayList<>();
		List<SysMenu> allMenus = menuService.listAllPermsByStatus(CoreConst.STATUS_VALID);
		List<SysMenu> hasMenus = roleService.listMenusByRoleId(Long.valueOf(roleId));
		for (SysMenu menu : allMenus) {
			MenuTreeListVo vo = new MenuTreeListVo();
			vo.setMenuId(menu.getMenuId());
			vo.setName(menu.getName());
			vo.setParentId(menu.getParentId());
			for (SysMenu hasMenu : hasMenus) {
				// 有权限则选中
				if (hasMenu.getMenuId().equals(menu.getMenuId())) {
					vo.setChecked(true);
					break;
				}
			}
			listVos.add(vo);
		}
		return listVos;
	}

	/**
	 * 分配权限
	 * 
	 * @param roleId
	 * @param menuIdStr
	 * @return
	 */
	@RequiresPermissions("role:edit")
	@PostMapping("/assign/menu")
	@ResponseBody
	public AjaxResultVo assignRole(String roleId, String menuIdStr) {
		try {
			List<Long> menuIdsList = new ArrayList<>();
			if (StringUtils.isNotBlank(menuIdStr)) {
				Long[] menuIdArray = Convert.toLongArray(",", menuIdStr);
				menuIdsList = Arrays.asList(menuIdArray);
			}
			AjaxResultVo resultVo = roleService.addAssignMenu(Long.valueOf(roleId), menuIdsList);
			AuthorizationUtils.clearAllCachedAuthorizationInfo();
			return resultVo;
		} catch (Exception e) {
			logger.error(String.format("分配权限异常 RoleController.assignRole%s", e));
			return AjaxResultVo.error("分配权限失败");
		}
	}

	/**
	 * 分配角色详情
	 * 
	 * @param model
	 * @param roleId
	 * @return
	 */
	@RequiresPermissions("role:edit")
	@GetMapping("/assignUsers")
	public String assignUsers(Model model, String roleId) {
		model.addAttribute("roleId", roleId);
		return "role/assignusers";
	}

	/**
	 * 分配角色列表查询
	 * 
	 * @param roleId
	 * @return
	 */
	@RequiresPermissions("role:edit")
	@PostMapping("/assign/user/list")
	@ResponseBody
	public AjaxResultVo assignUserList(String roleId) {
		try {
			List<SysUser> userList = userService.listUsers(new SysUser());
			Set<String> hasUsers = roleService.listUserIdsByRoleId(Long.valueOf(roleId));
			AjaxResultVo resultVo = AjaxResultVo.success();
			resultVo.put("rows", userList);
			resultVo.put("hasUsers", hasUsers);
			return resultVo;
		} catch (Exception e) {
			logger.error(String.format("分配角色列表查询异常 RoleController.assignUserList%s", e));
			return AjaxResultVo.error("查询失败");
		}
	}

	/**
	 * 取消角色分配
	 * 
	 * @param roleId
	 * @param userId
	 * @return
	 */
	@RequiresPermissions("role:edit")
	@PostMapping("/cancelAssign")
	@ResponseBody
	public AjaxResultVo cancelAssign(String roleId, String userId) {
		try {
			return roleService.cancelAssign(Long.valueOf(roleId), Long.valueOf(userId));
		} catch (Exception e) {
			logger.error(String.format("取消角色分配异常 RoleController.cancelAssign%s", e));
			return AjaxResultVo.error("取消角色分配失败");
		}
	}

	/**
	 * 分配用户
	 * 
	 * @param roleId
	 * @param userId
	 * @return
	 */
	@RequiresPermissions("role:edit")
	@PostMapping("/assignUser")
	@ResponseBody
	public AjaxResultVo assignUser(String roleId, String userId) {
		try {
			return roleService.assignUser(Long.valueOf(roleId), Long.valueOf(userId));
		} catch (Exception e) {
			logger.error(String.format("分配用户异常 RoleController.assignUser%s", e));
			return AjaxResultVo.error("分配用户失败");
		}
	}

}
